package com.example.demo.controller;


import com.example.demo.entity.Userinfo;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;


    /**
     *  通过代码方式手动实现事务.
     */
    // 注入手动实现 事务回滚/提交事务 不可或缺相关对象
    @Autowired
    private DataSourceTransactionManager transactionManager;
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/add")
    public Integer add(Userinfo userinfo) {
        // todo: 非空校验
        if(userinfo == null || !StringUtils.hasLength(userinfo.getUsername())
                            || !StringUtils.hasLength(userinfo.getPassword())) {
            return 0;
        }

        // 1. 开始事务.
        TransactionStatus transactionStatus =
                // 返回一个事务对象, 下面 rollback 或 commit 会用到.
                transactionManager.getTransaction(transactionDefinition);

        Integer result = userService.add(userinfo);
        System.out.println(result + " raw affected");

        // 回滚事务 和 提交事务 通常只用其一.
        // 2. 回滚事务
        // transactionManager.rollback(transactionStatus); // 回滚哪一个对象? 就将上面返回的事务对象传进来.
        // 3. 提交事务
        transactionManager.commit(transactionStatus);

        return result;
    }

    /**
     *  使用注解实现声明式事务(自动)
     */
    @Transactional // 声明式事务(自动提交).
    // @Transactional 可以加在类上或方法上, 在方法执行前自动开启事务,
    // 在方法执行完(没有任何异常), 自动提交事务, 但是如果在执行期间出现异常, 将自动 回滚事务.
    // 加在测试类或测试方法时, 则会自动回滚事务, 从而不会对数据库造成污染.
    @RequestMapping("/insert")
    public Integer insert(Userinfo userinfo) {
        // todo: 非空校验
        if(userinfo == null || !StringUtils.hasLength(userinfo.getUsername())
                || !StringUtils.hasLength(userinfo.getPassword())) {
            return 0;
        }

        // 这里重点看事务, 所以可以复用 add() 方法.
        Integer result = userService.add(userinfo);
        System.out.println(result + " raw affected");

        return result;
    }
}
